#!coding:utf-8
# vim: tabstop=4 shiftwidth=4 softtabstop=4
from lxml import etree
import logging
from cvirt.cnode.libvirtXmlObject.redirDevice import RedirDevice
from cvirt.cnode.libvirtXmlObject.charDevice import Channel

from cvirt.cnode.libvirtXmlObject.cpu import CPU
from cvirt.cnode.libvirtXmlObject.disk import GuestDisk
from cvirt.cnode.libvirtXmlObject.interface import GuestInterface
from cvirt.cnode.libvirtXmlObject.video import  GuestGraphics,GraphicVideo
from cvirt.cnode.libvirtXmlObject.soundAndinput import GuestSound, GuestInput
from cvirt.cnode.libvirtXmlObject.smbios import GuestSysinfo, GuestSMBIOS
from cvirt.cnode.libvirtXmlObject.baseDomain import XmlObject
from cvirt.cnode.libvirtXmlObject.clock import GuestClock
from cvirt.cnode.libvirtXmlObject.virtualController import *
from cvirt.cnode.libvirtXmlObject.virtualWatchdog import virtualWatchdog
LOG = logging.getLogger(__name__)

"""
    @author jay.han
"""
class Boot(object):

    BOOT_HARDDISK = "hd"
    BOOT_CDROM = "cdrom"
    BOOT_FLOPPY = "fd"
    BOOT_NETWORK = "network"

class Guest(XmlObject):
    ROOT_NAME = 'domain'
    def __init__(self, parse_xml=None, **kw):
        self.ns_prefix = 'qemu'
        self.ns_uri = 'http://libvirt.org/schemas/domain/qemu/1.0'
        self.type = 'kvm'
        self.uuid = None
        self.name = None
        self.memory = 1024 * 1024 * 500
        self.vcpus = 1
        self.cpu = None
        self.cpu_shares = None
        self.cpu_quota = None
        self.cpu_period = None
        self.acpi = False
        self.apic = False
        self.pae = True #默认开启pae
        self.clock = None
        self.sysinfo = None
        self.os_type = 'hvm'
        self.os_loader = None
        self.os_kernel = None
        self.os_initrd = None
        self.os_cmdline = None
        self.os_root = None
        self.os_init_path = None

        self.bootorder = []
        self.os_smbios = None

        # devices parse

        self.devices = []
        self.disks = []
        self.interfaces = []
        self.graphic = None
        self.sound = None
        self.usb_redr = None
        self.qemu_command = None

        self.bootmenu = False

        # self.controllers = []
        # self.redirdev = []
        
        self.watchdog = None
        super(Guest, self).__init__(parse_xml=parse_xml,**kw)


    def _parse_xml(self, xmldoc):
        self.type = xmldoc.get('type')
        for c in xmldoc.getchildren():
            if c.tag == "uuid":
                self.uuid = c.text
            elif c.tag == "name":
                self.name = c.text
            elif c.tag == 'vcpu':
                self.vcpus = int(c.text)
            elif c.tag == 'memory':
                self.memory = long(c.text)
            elif c.tag == 'sysinfo':
                self.sysinfo = GuestSysinfo()
                self.sysinfo._parse_xml(c)
            elif c.tag == 'os':
                self.parse_os(c)
            elif c.tag == 'features':
               self.parse_features(c)
            elif c.tag == 'clock':
                self.clock = GuestClock()
                self.clock._parse_xml(c)
            elif c.tag == 'cpu':
                self.cpu = CPU()
                self.cpu._parse_xml(c)
            elif c.tag == 'devices':
                self.parse_devices(c)
            elif c.tag == 'controller':
                self.devices.append(virtualController(parse_xml=etree.tostring(c)))
            elif c.tag == 'redirdev':
                self.devices.append(virtualRedirdev(parse_xml=etree.tostring(c)))

    def parse_devices(self,xml):
        for c in xml.getchildren():
            if c.tag == 'disk':
                disk = GuestDisk()
                disk._parse_xml(c)
                # self.devices.append(disk)
                self.disks.append(disk)
            elif c.tag == 'interface':
                interface = GuestInterface()
                interface._parse_xml(c)
                self.devices.append(interface)
            elif c.tag == 'graphics':
                graphic = GuestGraphics()
                graphic._parse_xml(c)
                self.graphic = graphic
                self.devices.append(graphic)
            elif c.tag == 'sound':
                sound = GuestSound()
                sound._parse_xml(c)
                self.sound = sound
                self.devices.append(sound)
            elif c.tag == 'channel':
                channel = Channel()
                channel._parse_xml(c)
                self.devices.append(channel)
            elif c.tag == 'redirdev':
                redir = RedirDevice()
                redir._parse_xml(c)
                self.devices.append(redir)
            elif c.tag == 'video':
                video = GraphicVideo()
                video._parse_xml(c)
                self.devices.append(video)
            elif c.tag == 'watchdog':
                self.watchdog = virtualWatchdog()
                self.watchdog._parse_xml(c)
            elif c.tag == 'input':
                input = GuestInput()
                input._parse_xml(c)
                self.devices.append(input)

    def parse_features(self,xml):
        for c in xml.getchildren():
            if c.tag == 'acpi':
                self.acpi = True
            elif c.tag == 'apic':
                self.apic = True
            elif c.tag == 'pae':
                self.pae = True

    def parse_os(self,xml):
        for c in xml.getchildren():
            if c.tag == 'type':
                self.os_type = c.text
            elif c.tag == 'boot':
                self.bootorder.append(c.get('dev'))
            elif c.tag == 'smbios':
                self.os_smbios = GuestSMBIOS(mode=c.get('mode'))
            elif c.tag == 'kernel':
                self.os_kernel = c.text
            elif c.tag == 'loader':
                self.os_loader = c.text
            elif c.tag == 'initrd':
                self.os_initrd = c.text
            elif c.tag == 'cmdline':
                self.os_cmdline = c.text
            elif c.tag == "root":
                self.os_root = c.text
            elif c.tag == 'init':
                self.os_init_path = c.text
            elif c.tag == 'bootmenu':
                if c.get('enable') == 'yes':
                    self.bootmenu = True


    def _format_basic_props(self, root):
        if self.uuid:
            root.append(self._set_text("uuid", self.uuid))
        root.append(self._set_text("name", self.name))
        root.append(self._set_text("memory", self.memory))
        root.append(self._set_text("vcpu", self.vcpus))

    def _format_os(self, root):
        os = etree.Element("os")
        os.append(self._set_text("type", self.os_type))
        if self.os_kernel:
            os.append(self._set_text("kernel", self.os_kernel))
        if self.os_loader:
            os.append(self._set_text("loader", self.os_loader))
        if self.os_initrd:
            os.append(self._set_text("initrd", self.os_initrd))
        if self.os_cmdline:
            os.append(self._set_text("cmdline", self.os_cmdline))
        if self.os_root:
            os.append(self._set_text("root", self.os_root))
        if self.os_init_path:
            os.append(self._set_text("init", self.os_init_path))

        for boot_dev in self.bootorder:
            os.append(etree.Element("boot", dev=boot_dev))

        if self.os_smbios is not None:
            os.append(self.os_smbios.get_xml_config())
        if self.bootmenu:
            os.append(etree.Element("bootmenu",enable='yes'))
        root.append(os)

    def _format_features(self, root):
        if self.acpi or self.apic:
            features = etree.Element("features")
            if self.acpi:
                features.append(etree.Element("acpi"))
            if self.apic:
                features.append(etree.Element("apic"))
            if self.pae:
                features.append(etree.Element("pae"))
            root.append(features)

    def _format_cputune(self, root):
        cputune = etree.Element("cputune")
        if self.cpu_shares is not None:
            cputune.append(self._set_text("shares", self.cpu_shares))
        if self.cpu_quota is not None:
            cputune.append(self._set_text("quota", self.cpu_quota))
        if self.cpu_period is not None:
            cputune.append(self._set_text("period", self.cpu_period))
        if len(cputune) > 0:
            root.append(cputune)

    def _format_devices(self, root):
        if len(self.devices) == 0:
            return
        devices = etree.Element("devices")
        for dev in self.devices:
            devices.append(dev.get_xml_config())
        for disk in self.disks:
            devices.append(disk.get_xml_config())
        if self.watchdog:
            devices.append(self.watchdog.get_xml_config())
        root.append(devices)

    def _format_command(self,root):
        if self.qemu_command:
            command = etree.Element("{%s}commandline" % self.ns_uri,nsmap={self.ns_prefix:self.ns_uri})
            command.append(etree.Element('{%s}%s' % (self.ns_uri, 'arg'),value=self.qemu_command))
            root.append(command)

    def _get_xml_config(self, root):
        root.set("type", self.type)


        self._format_basic_props(root)

        if self.sysinfo is not None:
            root.append(self.sysinfo.get_xml_config())

        self._format_os(root)
        self._format_features(root)
        self._format_cputune(root)

        if self.clock is not None:
            root.append(self.clock.get_xml_config())

        if self.cpu is not None:
            root.append(self.cpu.get_xml_config())

        self._format_devices(root)
        if self.qemu_command:
            self._format_command(root)

        # for c in self.controllers:
        #     root.append(c.get_xml_config())
        #
        # for r in self.redirdev:
        #     root.append(r.get_xml_config())

        return root

    def add_device(self, dev):
        self.devices.append(dev)

    def set_clock(self, clk):
        self.clock = clk
